package com.example.emos.workflow.controller;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.json.JSONUtil;
import com.example.emos.workflow.common.R;
import com.example.emos.workflow.controller.from.*;
import com.example.emos.workflow.service.WorkflowService;
import org.activiti.bpmn.model.BpmnModel;
import org.activiti.engine.*;
import org.activiti.engine.history.HistoricTaskInstance;
import org.activiti.engine.task.Task;
import org.activiti.image.impl.DefaultProcessDiagramGenerator;
import org.apache.commons.io.IOUtils;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

@RestController
@RequestMapping("/workflow")
public class WorkFlowController {

    @Resource
    private WorkflowService workflowService;

    @Resource
    private TaskService taskService;

    @Resource
    private ProcessEngine processEngine;

    @Resource
    private RepositoryService repositoryService;

    @Resource
    private RuntimeService runtimeService;

    @Resource
    private HistoryService historyService;

    /**
     * @Description: 启动任务
     * @Author: 张广焱
     * @Date: 2024-05-27  19:45:45
     */
    @PostMapping("/startMeetingProcess")
    public R startMeetingProcess(@RequestBody @Valid StartMeetingProcessForm form) {
        HashMap param = BeanUtil.toBean(form, HashMap.class);
        //是否需要归档
        param.put("filing", false);
        //工作流实例类型
        param.put("type", "会议申请");
        //启动工作流的日期
        param.put("createDate", DateUtil.today());
        //如果没发送总经理ID，说明申请人就是总经理
        if (form.getGmId() == null) {
            param.put("identity", "总经理");
            //会议状态通过
            param.put("result", "同意");
        } else {
            param.put("identity", "员工");
        }

        String instanceId = workflowService.startMeetingProcess(param);
        return R.ok().put("instanceId", instanceId);
    }


    /**
     * @Description: 查询任务列表
     * @Author: 张广焱
     * @Date: 2024-05-27  19:46:17
     */
    @PostMapping("/searchTaskByPage")
    public R searchTaskByPage(@Valid @RequestBody SearchTaskByPageForm form) {
        int page = form.getPage();
        int length = form.getLength();
        int start = (page - 1) * length;
        HashMap param = BeanUtil.toBean(form, HashMap.class);
        param.put("start", start);
        HashMap map = workflowService.searchTaskByPage(param);
        return R.ok().put("page", map);
    }

    /**
     * @Description: 查询任务列表详情
     * @Author: 张广焱
     * @Date: 2024-05-27  19:46:26
     */
    @PostMapping("/searchApprovalContent")
    public R searchApprovalContent(@Valid @RequestBody SearchApprovalContentForm form) {
        HashMap map = workflowService.searchApprovalContent(
                form.getInstanceId(),
                form.getUserId(),
                form.getRole(),
                form.getType(),
                form.getStatus()
        );
        return R.ok().put("content", map);
    }

    /**
     * @Description: bpmn图片生成
     * @Author: 张广焱
     * @Date: 2024-05-27  19:44:49
     */
    @PostMapping("/searchApprovalBpmn")
    public void searchApprovalBpmn(@Valid @RequestBody SearchApprovalBpmnForm form, HttpServletResponse response) {
        response.setContentType("image/jpg");
        //获取执行中的工作流实例中当下的任务，通过该任务可以获取BPMN定义
        Task task = taskService.createTaskQuery().processInstanceId(form.getInstanceId()).singleResult();
        BpmnModel bpmnModel = null;
        List activeActivityIds = null;
        if (task != null) {
            //获取BPMN流程定义 获取模型
            bpmnModel = repositoryService.getBpmnModel(task.getProcessDefinitionId());
            //获取正在执行中的节点和连线的id
            activeActivityIds = runtimeService.getActiveActivityIds(task.getExecutionId());
        } else {
            //获取BPMN流程定义
            HistoricTaskInstance taskInstance = historyService.createHistoricTaskInstanceQuery().processInstanceId(form.getInstanceId()).list().get(0);
            bpmnModel = repositoryService.getBpmnModel(taskInstance.getProcessDefinitionId());
            //因为任务流程已经执行结束，所以没有执行中的节点和连线
            activeActivityIds = new ArrayList<>();
        }

        DefaultProcessDiagramGenerator diagramGenerator = new DefaultProcessDiagramGenerator();
        //绘制bpmnModel代表的流程的流程图
        String os = System.getProperty("os.name").toLowerCase();
        //非Windows系统用SimSun字体
        String font = "SimSun";
        //Windows系统用宋体
        if (os.startsWith("win")) {
            font = "宋体";
        }
        // 参数：bpmn定义，图片类型，正在执行的节点，正在执行的连线，字体参数
        try (InputStream in = diagramGenerator.generateDiagram(bpmnModel, "jpg", activeActivityIds, activeActivityIds,
                font, font, font,
                processEngine.getProcessEngineConfiguration().getProcessEngineConfiguration().getClassLoader(), 1.0);
             //缓冲数据流
             BufferedInputStream bin = new BufferedInputStream(in);
             OutputStream out = response.getOutputStream();
             //输出缓冲流
             BufferedOutputStream bout = new BufferedOutputStream(out);
        ) {
            //把BPMN图片内容写到响应中
            IOUtils.copy(bin, bout);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * @Description: 审批工作流
     * @Author: 张广焱
     * @Date: 2024-05-27  19:44:38
     */
    @PostMapping("/approvalTask")
    public R approvalTask(@Valid @RequestBody ApprovalTaskForm form) {
        HashMap param = BeanUtil.toBean(form, HashMap.class);
        workflowService.approvalTask(param);
        return R.ok();
    }

        @PostMapping("/startLeaveProcess")
        public R startLeaveProcess(@Valid @RequestBody StartLeaveProcessForm form) {
            HashMap param = BeanUtil.toBean(form, HashMap.class);
            param.put("filing", false);
            param.put("type", "员工请假");
            param.put("createDate", DateUtil.today());

            String instanceId = workflowService.startLeaveProcess(param);
            return R.ok().put("instanceId", instanceId);
        }


    /**
     * @Description: 请假归档
     * @Author: 张广焱
     * @Date: 2024-06-02  12:49:27
     */
    @PostMapping("/archiveTask")
        public R archiveTask(@Valid @RequestBody ArchiveTaskForm form) {
            if (!JSONUtil.isJsonArray(form.getFiles())) {
                return R.error("files不是JSON数组");
            }
            HashMap param = new HashMap() {{
                put("taskId", form.getTaskId());
                put("userId", form.getUserId());
                put("files", JSONUtil.parseArray(form.getFiles()));
            }};
            workflowService.archiveTask(param);
            return R.ok();
        }

        @PostMapping("/startReimProcess")
        public R startReimProcess(@Valid @RequestBody StartReimProcessForm form) {
            HashMap param = BeanUtil.toBean(form, HashMap.class);
            param.put("filing", false);
            param.put("type", "报销申请");
            param.put("createDate", DateUtil.today());

            String instanceId = workflowService.startReimProcess(param);
            return R.ok().put("instanceId", instanceId);
        }
}
